package factory

import (
	"sync"

	"blockchain/bccsp"
	"blockchain/common/flogging"
	"github.com/pkg/errors"
)

var (
	defaultBCCSP       bccsp.BCCSP // 默认的的 BCCSP
	factoriesInitOnce  sync.Once   // 初始化一次使用的原子类
	factoriesInitError error       // 工厂初始化错误

	// 当InitFactories还没有被调用时(应该只发生在测试用例中)，临时使用这个BCCSP
	bootBCCSP         bccsp.BCCSP // 初始化工厂还没调用时候使用该BCCSP
	bootBCCSPInitOnce sync.Once   // 初始化一次使用的元子类

	logger = flogging.MustGetLogger("bccsp") // logger类
)

// BCCSPFactory用于获取BCCSP interface 的实例。
// Factroy 拥有一个Name去标记它
type BCCSPFactory interface {

	//工厂标记Name
	Name() string

	// 工厂使用opts 返回BCCSP
	Get(opts *FactoryOpts) (bccsp.BCCSP, error)
}

// GetDefault returns a non-ephemeral (long-term) BCCSP
// 通过GetDefault方法得到defaultBCCSP
// 如果defaultBCCSP不存在则会得到bootBCCSP
func GetDefault() bccsp.BCCSP {
	if defaultBCCSP == nil {
		logger.Debug("Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.")
		bootBCCSPInitOnce.Do(func() {
			var err error
			bootBCCSP, err = (&SWFactory{}).Get(GetDefaultOpts())
			if err != nil {
				panic("BCCSP Internal error, failed initialization with GetDefaultOpts!")
			}
		})
		return bootBCCSP
	}
	return defaultBCCSP
}

// 初始化得到BCCSP
func initBCCSP(f BCCSPFactory, config *FactoryOpts) (bccsp.BCCSP, error) {
	csp, err := f.Get(config)
	if err != nil {
		return nil, errors.Errorf("Could not initialize BCCSP %s [%s]", f.Name(), err)
	}

	return csp, nil
}
